home *** CD-ROM | disk | FTP | other *** search
/ FM Towns: Free Software Collection 4 / FM Towns Free Software Collection 4 - Disc 1.iso / t_os / wink / source / bplus.c next >
Encoding:
C/C++ Source or Header  |  1991-10-19  |  52.0 KB  |  2,106 lines

  1. /**************************************************************************
  2.  
  3.     FMR version Makeing by ken 89.9.5
  4.  
  5. ***************************************************************************/
  6. #include <stdio.h>
  7. #include <time.h>
  8. #include <string.h>
  9. #include <fmc.h>
  10.  
  11. #define unlink    remove
  12.  
  13. typedef long TIME_T;
  14.  
  15. extern int port,bps;
  16. extern unsigned char *cvram;
  17.  
  18. extern void    Send_Failure();
  19. extern TIME_T    gtime();
  20. extern int    kbhit();
  21. extern int    getch();
  22. extern void    wrtstr();
  23. extern void    Dmy_form();
  24. extern void    Dsp_vram();
  25.  
  26. TIME_T gtime(rt)
  27. long   *rt;
  28. {
  29.     long      l;
  30. /*************************************************************
  31.     time_t    t;
  32.     struct tm *dmy;
  33.  
  34.     time(&t);
  35.     dmy = localtime(&t);
  36.     l = dmy->tm_sec + dmy->tm_min * 60 + dmy->tm_hour * 3600;
  37. **************************************************************/
  38.     l = clock() / CLK_TCK;
  39.     if ( rt != NULL )
  40.     *rt = l;
  41.     return l;
  42. }
  43. int    Async_BuffeR_Check( chx )
  44. unsigned char *chx;
  45. {
  46.     int     data,len;
  47.     unsigned int status;
  48.  
  49.     RSB_read(port,&len);
  50.     if ( len != 0 ) {
  51.     RSB_receive(port,&data,&status);
  52.     *chx = data;
  53.     }
  54.     return len;
  55. }
  56. void   Async_Send(chx)
  57. int    chx;
  58. {
  59.     unsigned int status;
  60.  
  61.     RSB_send(port,chx,&status);
  62. }
  63. int  ST_Check_Abort()
  64. {
  65.     if ( kbhit() != 0 && getch() == '\x1B' )
  66.         return 1;
  67.     return 0;
  68. }
  69. void    ST_Yes_or_No(arg,yn)
  70. char    *arg;
  71. char    *yn;
  72. {
  73.     wrtstr(arg,17,20,0x02);
  74.     *yn = getch();
  75. }
  76. void    ST_Initialize()
  77. {
  78.     int    i;
  79.     char   tmp[160];
  80.     static char *menu[]={
  81.     "Msg     ","File    ","UpDow   ","Type    ","ComSent ",
  82.     "DataSent","ErrSent ","PacSent ","ComRate ","DataRate",
  83.     "Elapsed ",
  84.     "        ","        ","ComRead ","DataRead","ErrRead ",
  85.     "PacRead ","UplSize ","DowSize ","UplRem  ","DowRem  ",
  86.     "RemTime " };
  87.  
  88.     Dmy_form(tmp,50,0x98,0x95,0x99); 
  89.     wrtstr(tmp,15,7,0x06);
  90.  
  91.     Dmy_form(tmp,50,0x96,0x20,0x96); 
  92.     for ( i = 0 ; i < 13 ; i++ )
  93.         wrtstr(tmp,15,8+i,0x06);
  94.  
  95.     Dmy_form(tmp,50,0x9A,0x95,0x9B); 
  96.     wrtstr(tmp,15,21,0x06);
  97.  
  98.     wrtstr("  <<< B Plus Protocol(SM) Abort Hit ESC Key >>>",17,8,0x02);
  99.  
  100.     for ( i = 0 ; i < 22 ; i++ )
  101.     wrtstr(menu[i],17+(i/11)*24,9+(i%11),0x06);
  102. }
  103. void    ST_Terminate()
  104. {
  105.     Dsp_vram(cvram);
  106. }
  107. void    ST_Display_String(no,str)
  108. int    no;
  109. char    *str;
  110. {
  111.     wrtstr(str,27+(no/18)*24,9+(no%18),0x06);
  112. }
  113. void    ST_Display_Value(no,val)
  114. int    no;
  115. long    val;
  116. {
  117.     char     tmp[20];
  118.  
  119.     sprintf(tmp,"%7ld",val);
  120.     ST_Display_String(no,tmp);
  121. }
  122. #define STMsg        0
  123. #define STFile       1
  124. #define STUpDow      2
  125. #define STType       3
  126. #define STComSent    4
  127. #define STDataSent   5
  128. #define STErrSent    6
  129. #define STPacSent    7
  130. #define STComRate    8
  131. #define STDataRate   9
  132. #define STElapsed    10
  133.  
  134. #define STComRead    20
  135. #define STDataRead   21
  136. #define STErrRead    22
  137. #define STPacRead    23
  138. #define STUplSize    24
  139. #define STDowSize    25
  140. #define STUplRem     26
  141. #define STDowRem     27
  142. #define STRemTime    28
  143. /***********************************************************************/
  144. /****
  145.     BPLUS.INC - B Plus Protocol Support routines
  146.       (derived from BPROTO.INC)
  147.  
  148.     Copyright 1987, CompuServe Incorporated
  149.  
  150.     These routines may be used as-is or in modified form in any
  151.     personal computer terminal program to implement support of the
  152.     CompuServe B and B Plus Protocols for the purpose of transfering
  153.     information between CompuServe hosts and a personal computer.
  154.  
  155.     No warranty, expressed or implied, covers this code, or the specifications
  156.     of the B and B Plus Protocols.
  157.  
  158.  
  159.   Last update:
  160.        Russ Ranshaw      16-Dec-87   Corrected Upload Abort problems.
  161.        Russ Ranshaw      07-Apr-88   Corrected additional Abort problems.
  162.        Russ Ranshaw      09-Apr-88   Added Quote Set to + Packet.
  163.        Russ Ranshaw      10-Apr-88   Added Download Resume.
  164.        Russ Ranshaw      22-Apr-88   Added File Information to Download.
  165.                                      (File length only.)
  166.        Russ Ranshaw      11-May-88   Added check to control Upload degradation
  167.                                      under Send Ahead.
  168.        Russ Ranshaw      16-May-88   Remove debugging code for release
  169.                                      of Version 2.1
  170.        Russ Ranshaw      01-Jun-88   Added externally settable file size for
  171.                                      Downloads.  Use ST_Yes_or_No instead of
  172.                                      ST_Prompt to get Y/N response.
  173.        Russ Ranshaw      07-Jun-88   Added defensive check to see if Aborting
  174.                                      is already true.  Changed comm. rate
  175.                                      calculation.
  176.        Russ Ranshaw      23-Jun-88   Add check for <DLE><B> in ReSync.
  177.        Russ Ranshaw      04-Aug-88   Added WACK intercept to update the
  178.  
  179.                                      status display, mostly so that resumes
  180.                                      show some activity while the host calculates
  181.                                      it's CRC value.
  182.     Paul Resch     28-Aug-88   Converted to standard C code.
  183. ****/
  184.  
  185. /****************
  186. **
  187. **  This module implements the B-Protocol Functions.
  188. **
  189. **
  190. **  If you have any questions, contact:
  191. **      Russ Ranshaw, CompuServe Incorporated
  192. **         [70000,1010]
  193. **
  194. **  This source was originally derived from BP.C, written by
  195. **  Steve Wilhite, CompuServe Incorporated.
  196. **
  197. *****************/
  198.  
  199. /*
  200. const
  201.   UnitVersion = "2.2c";
  202.   UnitVerDate = "04 Aug 88";
  203.   UnitUpdBy   = "RWR";
  204. */
  205.  
  206. /****************************************************************************/
  207. /*
  208.  * C implementation notes:
  209.  *    Routines with names beginning "ST_" are not supplied.  They are
  210.  *        strictly console I/O.  Implement as needed, or see the PASCAL
  211.  *        version.
  212.  *    "Async_Send" is an extern that is passed a byte for output to the
  213.  *        serial port.
  214.  *    "Async_BuffeR_Read" is an extern that is passed the address of a byte.
  215.  *        If TRUE is returned, the byte will be from the serial port.
  216.  *        If FALSE is returned, the byte value is undefined.
  217.  *    The CRC subroutines are included in this module.
  218.  *
  219.  *    I have tried to keep as close as possible to Mr. Ranshaw's structure.
  220.  *    Please see the PASCAL source to clarify any confusion.
  221.  */
  222. /****************************************************************************/
  223.  
  224. #ifdef  DEBUG
  225. #define    STATIC
  226. #else
  227. #define    STATIC    static
  228. #endif
  229.  
  230. #define    TRUE    1
  231. #define    FALSE    0
  232.  
  233. STATIC    TIME_T    e_timer;
  234.  
  235. typedef char  maxstr[256];
  236.  
  237. int     BP_Auto_Resume = FALSE;  /* True to automatically attempt transfer */
  238.                                  /* resumption if the Initiator can do it  */
  239. int    BP_Use_File_Size = FALSE;
  240. long    BP_File_Size=0;
  241. /* BP_Quote_This is invoked to set bits in BP_Special_Quote_Set. */
  242. /* It must be called prior to calling BP_DLE_Seen for each character in the */
  243. /* ranges 0x00 -> 0x1f and 0x80 -> 0x9f that is to be quoted. */
  244. /*    BP_Quote_This (int Value); */
  245.  
  246. /* BP_Term_ENQ is invoked when Terminal Mode receives <ENQ> from host */
  247. /*    BP_Term_ENQ(); */
  248.  
  249. /* BP_Term_ESC_I is invoked when Terminal Mode receives <ESC><I> from host */
  250. /*    BP_Term_ESC_I (maxstr ESC_I_Response); */
  251.  
  252. /* BP_DLE_Seen is invoked when Terminal Mode receives <DLE> from host */
  253. /*    BP_DLE_Seen(); */
  254.  
  255. /*===========================================================================*/
  256.  
  257. typedef unsigned char QS_Array[8];
  258. typedef unsigned char QS_Array_p;
  259.  
  260. #define    bps300        0
  261. #define    bps600        1
  262. #define    bps1200        2
  263. #define    bps2400        3
  264. #define    bps4800        4
  265. #define    bps9600        5
  266. int    PortBps = bps2400;
  267.  
  268. STATIC    int    seq_num;       /* Current Sequence Number - init by Term_ENQ */
  269. STATIC    unsigned short    checksum;          /* May hold CRC */
  270.  
  271.          /* Initiator's Parameters */
  272. STATIC  unsigned char   His_WS,                      /* Initiator's Window Send     */
  273.   His_WR,                      /* Initiator's Window Receive  */
  274.   His_BS,                      /* Initiator's Block Size      */
  275.   His_CM;               /* Initiator's Check Method    */
  276. STATIC    QS_Array    His_QS;           /* Initiator's Quote Set */
  277.          /* The next 3 Parameters are for the B Plus File Transfer Application */
  278. STATIC    unsigned char His_DR=0, /* Initiator's Download Recovery Option */
  279.   His_UR=0,                     /* Initiator's Upload Recovery Option */
  280.   His_FI=0;                   /* Initiator's File Information Option */
  281.  
  282.          /* Negotiated Parameters */
  283. STATIC    unsigned char  Our_WS=0,    /* Negotiated Window Send   */
  284.   Our_WR=0,            /* Negotiated Window Receive */
  285.   Our_BS=0,            /* Negotiated Block Size     */
  286.   Our_CM=0;            /* Negotiated Check Method   */
  287. STATIC    QS_Array    Our_QS;    /* Our Quote Set */
  288. STATIC    unsigned char Our_DR=0,    /* Our Download Recovery Option */
  289.   Our_UR=0,            /* Our Upload Recovery Option */
  290.   Our_FI=0,            /* Our File Information Option */
  291.   Def_DR=0,            /* User's preferred DOW Resume option */
  292.   Def_BS=0;                       /* Default Block Size: varies depending */
  293.                     /* on the baud in use */
  294. STATIC unsigned char Port_Update_Rate=0;
  295.     /* Number of port bytes between Status */
  296.                                /* upldates for the Port     */
  297. STATIC    int    B_Plus=0;       /* True if B Plus in effect  */
  298. STATIC    int    Use_CRC=0;       /* True if CRC in effect     */
  299. STATIC    int    BP_Special_Quoting = 0;/* True to use BP_Special_Quote_Set */
  300. STATIC    QS_Array BP_Special_Quote_Set =  /* User's specified Quote Set */
  301.          {0x14, 0x00, 0xd4, 0x00,   /* ETX ENQ DLE XON XOFF NAK */
  302.           0x00, 0x00, 0x00, 0x00
  303.          };
  304.  
  305. STATIC    int    Buffer_Size=0;       /* Our_BS * 4                */
  306. STATIC    int    SA_Max=0;   /* 1 if SA not enabled, else Max_SA */
  307. STATIC    int    SA_Error_Count=0;   /* # of times S_Send_Data called */
  308.  
  309. STATIC    unsigned char    Quote_Table[256];   /* The quoting table */
  310.  
  311. STATIC    QS_Array  DQ_Full =
  312.           {0xff, 0xff, 0xff, 0xff,
  313.        0xff, 0xff, 0xff, 0xff
  314.           };
  315. STATIC    QS_Array  DQ_Default =
  316.         {0x14, 0x00, 0xd4, 0x00,    /* ETX ENQ DLE XON XOFF NAK */
  317.          0x00, 0x00, 0x00, 0x00
  318.         };
  319. STATIC    QS_Array  DQ_Minimal =
  320.         {0x14, 0x00, 0xd4, 0x00,    /* ETX ENQ DLE XON XOFF NAK */
  321.          0x00, 0x00, 0x00, 0x00
  322.         };
  323. STATIC    QS_Array  DQ_Extended =
  324.        {0x14, 0x00, 0xd4, 0x00,     /* ETX ENQ DLE XON XOFF NAK */
  325.         0x00, 0x00, 0x50, 0x00      /* XON XOFF */
  326.        };
  327.  
  328. #define   Max_Buf_Size   1032        /* Largest data block we can handle */
  329. #define   Max_SA  2                  /* Maximum number of waiting Packets */
  330.  
  331. #define   Def_Buf_Size   511         /* Default data block               */
  332. #define   Def_WS         1           /* I can send 2 Packets ahead       */
  333. #define   Def_WR         1           /* I can receive single send-ahead  */
  334. #define   Def_CM         1           /* I can handle CRC                 */
  335. #define   Def_DQ         1           /* I can handle non-quoted NUL      */
  336.                                        /* (including the `Tf' Packet       */
  337. #define   Def_UR         0           /* I can NOT handle Upload Recovery */
  338. #define   Def_FI         1           /* I can handle File Information */
  339.  
  340. #define   max_Errors     10
  341.  
  342.  
  343. /* Receive States */
  344.  
  345. #define   R_Get_DLE       0
  346. #define   R_Get_B         1
  347. #define   R_Get_Seq       2
  348. #define   R_Get_Data      3
  349. #define   R_Get_Check     4
  350. #define   R_Send_ACK      5
  351. #define   R_Timed_Out     6
  352. #define   R_Success       7
  353.  
  354. /* Send States */
  355.  
  356. #define   S_Get_DLE       1
  357. #define   S_Get_Num       2
  358. #define   S_Have_ACK      3
  359. #define   S_Get_Packet    4
  360. #define   S_Skip_Packet   5
  361. #define   S_Timed_Out     6
  362. #define   S_Send_NAK      7
  363. #define   S_Send_ENQ      8
  364. #define   S_Send_Data     9
  365.  
  366. /* Other Constants */
  367.  
  368. #define   dle   16
  369. #define   etx   03
  370. #define   nak   21
  371. #define   enq   05
  372.  
  373. typedef char    lstr[256];
  374. typedef struct {
  375.     int    seq;    /* Packet's sequence number  */
  376.     int    num;    /* Number of bytes in Packet */
  377.     unsigned char    buf[Max_Buf_Size]; /* Actual Packet data        */
  378.     } buf_type;
  379.  
  380. /****************************************************************************/
  381. void    ltoa( n, s )
  382. register long    n;
  383. register char    *s;
  384. {
  385.     register char    *t;
  386.     register long    i;
  387.     register char    c;
  388.     long    sign;
  389.     long    divten;
  390.  
  391.     if( (sign = n) < 0 )
  392.         n = -n;
  393.     t = s;
  394.     do
  395.     {
  396.         i = (divten = (n / 10)) * 10;    /* get ones digit (sigh) */
  397.  
  398.         *t++ = ( n - i ) + '0';
  399.     } while( (n = divten) > 0 );
  400.     if( sign < 0 )
  401.         *t++ = '-';
  402.     *t-- = '\0';
  403.     while( s < t )
  404.     {
  405.         c = *t;
  406.         *t-- = *s;
  407.         *s++ = c;
  408.     }
  409. }
  410. /****************************************************************************/
  411. /*
  412.   Clear_Quote_Table:
  413.     Initialize Quote_Table to all zeros (nothing quoted).
  414. */
  415.  
  416. STATIC void Clear_Quote_Table()
  417. {
  418.     int    i;
  419.  
  420.  
  421.     for( i = 0; i<=255; i++ )
  422.         Quote_Table [i] = 0;
  423. }
  424.  
  425. /*
  426.   Update_Quote_Table:
  427.     Sets the i-th entry of Quote_Table to the necessary quoting character
  428.     according to the i-th bit of the supplied Quote Set.
  429. */
  430.  
  431. STATIC void Update_Quote_Table (Quote_Set)
  432. QS_Array_p *Quote_Set;
  433. {
  434.     int    i, j, k;
  435.     unsigned char    b, c;
  436.  
  437.     k = 0;
  438.     c = 0x40;
  439.  
  440.     for( i = 0; i<=7; i++ )
  441.     {
  442.         if( i == 4 )
  443.                     /* Switch to upper control set */
  444.         {
  445.             c = 0x60;
  446.             k = 128;
  447.         }
  448.  
  449.         b = Quote_Set [i];
  450.  
  451.         for (j = 0; j<=7; j++ )
  452.         {
  453.             if ((b & 0x80) != 0)
  454.                 Quote_Table [k] = c;
  455.  
  456.             b = b << 1;
  457.             c = c + 1;
  458.             k = k + 1;
  459.         }
  460.     }
  461. }
  462.  
  463. /* BP_Quote_This sets bits in BP_Special_Quote_Set.                 */
  464. /* It sets BP_Special_Quoting true to use the special quote set.    */
  465. /* If Value = -1, the Special Quote Set is restored to its default. */
  466.  
  467. void    BP_Quote_This (Value)
  468. int    Value;
  469. {
  470.     int    i, j;
  471.  
  472.     if ((Value >= 0x00 && Value <= 0x1F) ||
  473.         (Value >= 0x80 && Value <= 0x9f) )
  474.     {
  475.         if (Value > 0x1f)
  476.         {
  477.             i = 4;
  478.             Value = Value & 0x1f;
  479.         }
  480.         else
  481.             i = 0;
  482.  
  483.         i = i + Value / 8;       /* = index into BP_Special_Quote_Set */
  484.         j = Value % 8;           /* = Bit number in the i-th byte */
  485.         BP_Special_Quote_Set [i] =
  486.             BP_Special_Quote_Set [i] || (0x80 >> j);
  487.         BP_Special_Quoting = TRUE;
  488.     }
  489.     else if (Value == -1)              /* Restore the Quote Set? */
  490.     {
  491.         for( i=0; i<sizeof(DQ_Minimal); i++ )
  492.             BP_Special_Quote_Set[i] = DQ_Minimal[i];
  493.         BP_Special_Quoting = FALSE;
  494.     }
  495. }
  496.  
  497. /*
  498.   BP_Term_ENQ is called when the terminal emulator receives the character <ENQ>
  499.   from the host.  Its purpose is to initialize for B Protocol and tell the
  500.   host that we support B Plus.
  501. */
  502.  
  503.  
  504. void    BP_Term_ENQ()
  505. {
  506.     int i;
  507.  
  508.     seq_num = 0;
  509.     Buffer_Size = 512;               /* Set up defaults */
  510.     Our_WS = 0;
  511.     Our_WR = 0;
  512.     Our_BS = 4;
  513.     Our_CM = 0;
  514.     Our_DR = 0;
  515.     Our_UR = 0;
  516.     Our_FI = 0;
  517.  
  518.     B_Plus      = FALSE;             /* Not B Plus Protocol */
  519.     Use_CRC     = FALSE;             /* Not CRC_16      */
  520.     SA_Max      = 1;                 /* Single Packet send */
  521.     SA_Error_Count = 0;              /* No Upload errors yet */
  522.  
  523.   /* Set up Our prefered Quoting Mask */
  524.     for( i=0; i<sizeof(DQ_Minimal); i++ )
  525.         Our_QS[i] = DQ_Minimal[i];
  526.  
  527.     Clear_Quote_Table();
  528.     Update_Quote_Table (Our_QS);
  529.  
  530.     Async_Send (dle);
  531.     Async_Send ('+');
  532.     Async_Send ('+');
  533.     Async_Send (dle);
  534.     Async_Send ('0');
  535. }
  536.  
  537. /*
  538.   BP_Term_ESC_I is called when <ESC><I> is received by the terminal emulator.
  539.   Note that CompuServe now recognizes the string ",+xxxx" as the final field.
  540.   THis provides a checksum (xxxx being the ASCII decimal representation of the
  541.   sum of all characters in the response string from # to +.  The purpose of
  542.   the checksum is to eliminate the need for retransmission and comparison of
  543.   the response.
  544. */
  545.  
  546.  
  547. void    BP_Term_ESC_I (esc_I_Response)
  548. char    esc_I_Response[];
  549. {
  550.     int    i;
  551.     maxstr    t;
  552.     int    cks;    /* checksum */
  553.  
  554.     cks = 0;
  555.  
  556.     for (i = 0; i<strlen (esc_I_Response); i++ )
  557.     {
  558.         Async_Send (esc_I_Response [i]);
  559.         cks += esc_I_Response [i];
  560.     }
  561.  
  562.     Async_Send (',');
  563.     Async_Send ('+');
  564.     cks = cks + ',' + '+';
  565.  
  566.     ltoa( (long)cks, t );
  567.  
  568.     i = 4 - strlen( t );    /* zero-fill */
  569.     while( i-- )
  570.         Async_Send( '0' );
  571.  
  572.     for (i = 0; i<strlen (t); i++ )
  573.         Async_Send (t [i]);
  574.  
  575.     Async_Send (0x0d);    /* <CR> */
  576. }
  577.  
  578.  
  579. /*
  580.   BP_DLE_Seen is called from the main program when the character <DLE> is
  581.   received from the host.
  582.  
  583.   This routine calls Read_Packet and dispatches to the appropriate
  584.   handler for the incoming Packet.
  585. */
  586.  
  587.  
  588. STATIC    int    ttime=0,
  589.     R_Size=0,           /* size of receiver buffer */
  590.     ch=0;               /* current character */
  591.  
  592. STATIC    int    xoff_flag=0,
  593.     Timed_Out=0,            /* we timed out before receiving character */
  594.     Packet_Received=0,      /* True if a Packet was received */
  595.     masked=0;               /* true if ctrl character was quoted */
  596.  
  597. STATIC    buf_type    SA_Buf[Max_SA+1];  /* Send-ahead buffers */
  598.  
  599. STATIC    int    SA_Next_to_ACK=0;    /* Which SA_Buf is waiting for an ACK */
  600. STATIC    int    SA_Next_to_Fill=0;   /* Which SA_Buf is ready for new data */
  601. STATIC    int    SA_Waiting=0;        /* Number of SA_Buf's waiting for ACK */
  602. STATIC    int    Aborting=0;          /* True if aborting the transfer ]*/
  603.  
  604. STATIC    unsigned char    R_buffer[Max_Buf_Size];
  605. STATIC    lstr    filename=0;                   /* pathname */
  606. STATIC    int        S_Counter=0;                  /* Used to pace status update */
  607. STATIC    int        R_Counter=0;
  608. STATIC    long    S_Com_Data=0;                 /* Comm Port Data traffic */
  609. STATIC    long    R_Com_Data=0;
  610. STATIC    long    S_File_Data=0;                /* File Data Traffic */
  611. STATIC  long    R_File_Data=0;
  612. STATIC    long    S_Packet_Count=0;             /* Packet count */
  613. STATIC    long    R_Packet_Count=0;
  614. STATIC    long    S_Error_Count=0;               /* Error count */
  615. STATIC    long    R_Error_Count=0;
  616. STATIC    long    S_File_Size=0;         /* Length of file already sent */
  617. STATIC    long    R_File_Size=0;         /* Length of file already received */
  618. STATIC    long    S_Remaining=0;         /* # bytes remaining to be sent */
  619. STATIC    long    R_Remaining=0;         /* # bytes reamining to be received */
  620. STATIC    long    Com_Rate=0;            /* Comm. bytes per second */
  621. STATIC    long    Data_Rate=0;           /* Effective Data bytes per second */
  622. STATIC    long    Time_Estimate=0;       /* Estimated time until completion */
  623. STATIC    int    Resume_Flag=0;         /* TRUE if attempting a DOW resume */
  624.  
  625. /***************************************************************************/
  626. /*
  627.  * crc
  628.  *
  629.  * Calculates XMODEM-style CRC (uses the CCITT V.41 polynomial but
  630.  * completely backwards from the normal bit ordering).
  631.  */
  632.  
  633.  
  634. STATIC    unsigned    crc_table[] = {
  635.         0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
  636.         0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
  637.         0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,
  638.         0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE,
  639.         0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485,
  640.         0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D,
  641.         0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4,
  642.         0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC,
  643.  
  644.         0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,
  645.         0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B,
  646.         0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12,
  647.         0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A,
  648.         0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41,
  649.     0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49,
  650.         0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70,
  651.         0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78,
  652.         0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F,
  653.         0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
  654.         0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E,
  655.         0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256,
  656.         0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D,
  657.         0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
  658.         0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C,
  659.         0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634,
  660.         0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB,
  661.         0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3,
  662.         0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A,
  663.         0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92,
  664.         0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9,
  665.         0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1,
  666.         0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8,
  667.         0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0
  668.     };
  669.  
  670. STATIC    unsigned int    crc_16;
  671.  
  672. /*
  673.  * Init_CRC initializes for XMODEM style CRC calculation by setting
  674.  * crc_16 to value.  Typically value is 0 for XMODEM and -1 for
  675.  * B+ Protocl.  It returns the initial value.
  676.  */
  677. STATIC    int    Init_CRC (value)
  678. int    value;
  679. {
  680.     return( crc_16 = value );
  681. }
  682.  
  683. /*
  684.   Upd_CRC updates crc_16 and returns the updated value. */
  685.  
  686. STATIC    unsigned int    Upd_CRC (value)
  687. unsigned int    value;
  688. {
  689.     crc_16 = crc_table [((crc_16 >> 8) ^ (value)) & 0xff] ^ (crc_16 << 8);
  690.     return( crc_16 );
  691. }
  692. /***************************************************************************/
  693.  
  694. STATIC    void do_checksum (c)
  695. int    c;
  696. {
  697.     if (B_Plus && Use_CRC)
  698.         checksum = Upd_CRC ((unsigned short)c);
  699.     else
  700.     {
  701.         checksum = checksum << 1;
  702.  
  703.         if (checksum > 255)
  704.             checksum = (checksum & 0xff) + 1;
  705.  
  706.         checksum += c;
  707.  
  708.         if (checksum > 255)
  709.             checksum = (checksum & 0xff) + 1;
  710.     }
  711. }
  712.  
  713. STATIC    void send_byte (ch)
  714. unsigned char    ch;
  715. {
  716.     Async_Send (ch);
  717.     S_Com_Data++;
  718.     S_Counter++;
  719.     S_Counter = S_Counter % Port_Update_Rate;
  720.  
  721.     if (S_Counter == 0)
  722.         ST_Display_Value (STComSent, S_Com_Data);
  723. }
  724.  
  725. STATIC void send_masked_byte (ch)
  726. int    ch;
  727. {
  728.     ch &= 0xff;
  729.  
  730.     if (Quote_Table [ch] != 0)
  731.     {
  732.         send_byte (dle);
  733.         send_byte (Quote_Table [ch]);
  734.     }
  735.     else
  736.         send_byte (ch);
  737. }
  738.  
  739. STATIC void Send_ACK()
  740. {
  741.     send_byte (dle);
  742.     send_byte (seq_num + '0');
  743. }
  744.  
  745. STATIC void Send_NAK()
  746. {
  747.     send_byte (nak);
  748. }
  749.  
  750. /***********************
  751. STATIC void Send_ENQ()
  752. {
  753.     send_byte (enq);
  754. }
  755. ***********************/
  756.  
  757. STATIC int read_byte()
  758. {
  759.     unsigned char    chx;
  760.     unsigned short    Hiber;
  761.     TIME_T    start;
  762.  
  763.     Timed_Out = FALSE;
  764.     start = gtime(NULL);
  765.  
  766.     if ( !Aborting )
  767.         Hiber = 30;
  768.     else
  769.         Hiber = 10;
  770.  
  771.     while ( !Async_BuffeR_Check( &chx ) )
  772.     {
  773.  
  774.         if (gtime(NULL) - start >= Hiber)
  775.         {
  776.             Timed_Out = TRUE;
  777.             return( FALSE );
  778.         }
  779.     }
  780.  
  781.     ch = chx;
  782.     R_Com_Data++;
  783.     R_Counter++;
  784.     R_Counter = R_Counter % Port_Update_Rate;
  785.  
  786.     if (R_Counter == 0 )
  787.         ST_Display_Value (STComRead, R_Com_Data);
  788.  
  789.     return(TRUE);
  790. }
  791.  
  792.  
  793. STATIC int read_masked_byte()
  794. {
  795.     masked = FALSE;
  796.  
  797.     if (read_byte() == FALSE)
  798.         return(FALSE);
  799.  
  800.     if (ch == dle)
  801.     {
  802.         if (read_byte() == FALSE)
  803.             return(FALSE);
  804.  
  805.         if (ch < 0x60)
  806.             ch = ch & 0x1f;
  807.         else
  808.             ch = (ch & 0x1f) | 0x80;
  809.  
  810.         masked = TRUE;
  811.     }
  812.  
  813.     return(TRUE);
  814. }
  815.  
  816. /*
  817.   Increment Sequence Number
  818. */
  819.  
  820. STATIC    int    Incr_Seq (value)
  821. int    value;
  822. {
  823.     if (value == 9)
  824.         return( 0);
  825.     else
  826.         return(value + 1);
  827. }
  828.  
  829.  
  830. STATIC    int    Read_Packet (Lead_in_Seen, From_Send_Packet)
  831. int    Lead_in_Seen;
  832. int    From_Send_Packet;
  833. /*   Lead_in_Seen is true if the <DLE><B> has been seen already.  */
  834.  
  835.  
  836. /*   From_Send_Packet is true if called from Send_Packet          */
  837. /*        (causes exit on first error detected)                   */
  838.  
  839. /*   Returns True if Packet is available from host. */
  840.  
  841. {
  842.     short  State,
  843.         next_seq,
  844.         block_num,
  845.         errors,
  846.         new_cks;
  847.     int    i;
  848.     int    NAK_Sent;
  849.  
  850.     if (Packet_Received)      /* See if a Packet was picked up on a call to */
  851.                       /* Get_ACK */
  852.     {
  853.         Packet_Received = FALSE;
  854.         return( TRUE);
  855.     }
  856.  
  857.     NAK_Sent = FALSE;
  858.  
  859.     for( i=0; i<Buffer_Size; i++ )
  860.         R_buffer[i] = 0;
  861.  
  862.     next_seq = (seq_num +  1) % 10;
  863.     errors = 0;
  864.  
  865.     if (Lead_in_Seen)           /* Start off on the correct foot */
  866.         State = R_Get_Seq;
  867.     else State = R_Get_DLE;
  868.  
  869.     while( TRUE )
  870.     {
  871.         ttime = 300;
  872.  
  873.         switch  (State) {
  874.  
  875.         case R_Get_DLE :
  876.             if (ST_Check_Abort() && !Aborting)
  877.             {
  878.                 ST_Display_String (STMsg, "Aborting download per your request");
  879.                 Send_Failure ("AAborted by user");
  880.                 return(FALSE);
  881.             }
  882.  
  883.             if ( !read_byte() )
  884.                 State = R_Timed_Out;
  885.             else if ((ch & 0x7F) == dle )
  886.                 State = R_Get_B;
  887.             else if ((ch & 0x7F) == enq )
  888.                 State = R_Send_ACK;
  889.             break;
  890.  
  891.         case R_Get_B :
  892.             if (!read_byte())
  893.                 State = R_Timed_Out;
  894.             else if ((ch & 0x7F) == 'B')
  895.                 State = R_Get_Seq;
  896.             else if (ch == enq)
  897.                 State = R_Send_ACK;
  898.             else if (ch == ';')
  899.             {
  900.                 ST_Display_Value (STComRead, R_Com_Data);
  901.                 State = R_Get_DLE;
  902.             }
  903.             else State = R_Get_DLE;
  904.             break;
  905.  
  906.         case R_Get_Seq :
  907.             if( Resume_Flag )   /* Improve status display for DOW resume */
  908.             {
  909.                 e_timer = gtime(NULL);
  910.                 R_Com_Data = 2;
  911.             }
  912.             if (!read_byte())
  913.                 State = R_Timed_Out;
  914.             else if (ch == enq)
  915.                 State = R_Send_ACK;
  916.             else
  917.             {
  918.                 if (B_Plus && Use_CRC)
  919.                     checksum = Init_CRC (0xffff);
  920.                 else checksum = 0;
  921.  
  922.                 block_num = ch - '0';
  923.  
  924.                 do_checksum (ch);
  925.  
  926.                 i = 0;
  927.                 State = R_Get_Data;
  928.             }
  929.             break;
  930.  
  931.         case R_Get_Data :
  932.             if (!read_masked_byte())
  933.                 State = R_Timed_Out;
  934.             else if ((ch == etx) && !masked)
  935.             {
  936.  
  937.                 do_checksum (etx);
  938.                 State = R_Get_Check;
  939.             }
  940.             else
  941.             {
  942.                 R_buffer[i] = ch;
  943.                 i = i + 1;
  944.                 do_checksum (ch);
  945.             }
  946.             break;
  947.  
  948.         case R_Get_Check :
  949.             if (!read_masked_byte())
  950.                 State = R_Timed_Out;
  951.             else
  952.             {
  953.                 if (B_Plus && Use_CRC)
  954.                 {
  955.                     checksum = Upd_CRC ((unsigned int)ch);
  956.  
  957.                     if (!read_masked_byte())
  958.                         new_cks = checksum ^ 0xff;
  959.                     else
  960.                     {
  961.                         checksum =
  962.                             Upd_CRC((unsigned int)ch);
  963.                         new_cks = 0;
  964.                     }
  965.                 }
  966.                 else new_cks = ch;
  967.  
  968.                 if (new_cks != checksum)
  969.                     State = R_Timed_Out;
  970.                 else if (R_buffer[0] == 'F') /* Watch for Failure Packet */
  971.                     State = R_Success; /* which is accepted regardless */
  972.                 else if (block_num == seq_num) /* Watch for duplicate block */
  973.                     State = R_Send_ACK; /* Simply ACK it */
  974.                 else if (block_num != next_seq)
  975.                     State = R_Timed_Out; /* Bad seq num */
  976.                 else State = R_Success;
  977.             }
  978.             break;
  979.  
  980.         case R_Timed_Out :
  981.             errors++;
  982.  
  983.             if ((errors > max_Errors) || (From_Send_Packet))
  984.                 return( FALSE );
  985.  
  986.             if (!NAK_Sent || !B_Plus)
  987.             {
  988.                 R_Error_Count++;
  989.                 ST_Display_Value (STErrRead, R_Error_Count);
  990.                 NAK_Sent = TRUE;
  991.                 Send_NAK();
  992.             }
  993.  
  994.             State = R_Get_DLE;
  995.             break;
  996.  
  997.         case R_Send_ACK :
  998.  
  999.             if (!Aborting)
  1000.                 Send_ACK();
  1001.  
  1002.             State = R_Get_DLE;        /* wait for the next block */
  1003.             break;
  1004.  
  1005.         case R_Success :
  1006.             ST_Display_Value (STComRead, R_Com_Data);
  1007.             ST_Display_Value (STComSent, S_Com_Data);
  1008.  
  1009.             if (!Aborting)
  1010.                 seq_num = block_num;
  1011.  
  1012.             R_Size = i;
  1013.             R_Packet_Count++;
  1014.             ST_Display_Value (STPacRead, R_Packet_Count);
  1015.             return(TRUE);
  1016.  
  1017.         }
  1018.     }
  1019.  
  1020. } /* Read_Packet */
  1021.  
  1022. STATIC    void Send_Data (BuffeR_Number)
  1023. int    BuffeR_Number;
  1024. {
  1025.     int    i;
  1026.     buf_type    *p;
  1027.  
  1028.     p = &SA_Buf [BuffeR_Number];
  1029.  
  1030.     if (B_Plus && Use_CRC)
  1031.         checksum = Init_CRC (0xffff);
  1032.     else checksum = 0;
  1033.  
  1034.     send_byte (dle);
  1035.     send_byte ('B');
  1036.  
  1037.     send_byte (p->seq + '0');
  1038.     do_checksum (p->seq + '0');
  1039.  
  1040.     for (i = 0; i<=p->num; i++ )
  1041.     {
  1042.         send_masked_byte (p->buf [i]);
  1043.         do_checksum (p->buf[i]);
  1044.     }
  1045.  
  1046.     send_byte (etx);
  1047.     do_checksum (etx);
  1048.  
  1049.      if (B_Plus && Use_CRC)
  1050.         send_masked_byte (checksum >> 8);
  1051.  
  1052.     send_masked_byte (checksum);
  1053.  
  1054. }
  1055.  
  1056. STATIC    int    Incr_SA (Old_Value)
  1057. int    Old_Value;
  1058. {
  1059.     if (Old_Value == Max_SA)
  1060.         return(0);
  1061.     else
  1062.         return(Old_Value + 1);
  1063. }
  1064.  
  1065. /*
  1066.   ReSync is called to restablish syncronism with the remote.  This is
  1067.   accomplished by sending <ENQ><ENQ> and waiting for the sequence
  1068.   <DLE><d><DLE><d> to be received, ignoring everything else.
  1069.  
  1070.   Return is -1 on time out, `B` if <DLE><B> seen, else the digit <d>.
  1071. */
  1072.  
  1073. STATIC    int    ReSync()
  1074. #define      Get_First_DLE     1
  1075. #define      Get_First_Digit   2
  1076. #define      Get_Second_DLE    3
  1077. #define      Get_Second_Digit  4
  1078. {
  1079.     int    State,
  1080.     Digit_1;
  1081.  
  1082.     send_byte (enq);     /* Send <ENQ><ENQ> */
  1083.     send_byte (enq);
  1084.     State = Get_First_DLE;
  1085.  
  1086.     while(1)
  1087.     {
  1088.         switch (State) {
  1089.         case Get_First_DLE :
  1090.             if (!read_byte())
  1091.                 return(-1);
  1092.  
  1093.             if (ch == dle)
  1094.                 State = Get_First_Digit;
  1095.             break;
  1096.  
  1097.         case Get_First_Digit :
  1098.             if (!read_byte())
  1099.                 return(-1);
  1100.  
  1101.             if ((ch >= '0') && (ch <= '9'))
  1102.             {
  1103.                 Digit_1 = ch;
  1104.                 State = Get_Second_DLE;
  1105.             }
  1106.             else if (ch == 'B')
  1107.                 return( ch );
  1108.             break;
  1109.  
  1110.         case Get_Second_DLE :
  1111.             if (!read_byte())
  1112.                 return(-1);
  1113.  
  1114.             if (ch == dle)
  1115.                 State = Get_Second_Digit;
  1116.             break;
  1117.  
  1118.         case Get_Second_Digit :
  1119.             if (!read_byte())
  1120.                 return(-1);
  1121.  
  1122.             if ((ch >= '0') && (ch <= '9'))
  1123.             {
  1124.                 if (Digit_1 == ch  )
  1125.                     return(ch);
  1126.                 else if (ch == 'B')
  1127.                     return( ch );
  1128.                 else
  1129.                 {
  1130.                     Digit_1 = ch;
  1131.                     State = Get_Second_DLE;
  1132.                 }
  1133.             }
  1134.             else State = Get_Second_DLE;
  1135.             break;
  1136.  
  1137.         } /* case */
  1138.     }  /* while TRUE */
  1139. }
  1140.  
  1141. /*
  1142.   Get_ACK is called to wait until the SA_Buf indicated by SA_Next_to_ACK
  1143.   has been ACKed by the host.
  1144. */
  1145.  
  1146. STATIC    int    Get_ACK()
  1147. {
  1148.     int    State,
  1149.         errors,
  1150.         block_num,
  1151.         i;
  1152. /*  int    new_cks;*/
  1153.     int    Sent_ENQ;
  1154.     int    SA_Index;
  1155.  
  1156.     Packet_Received = FALSE;
  1157.     errors = 0;
  1158.     Sent_ENQ = FALSE;
  1159.     State = S_Get_DLE;
  1160.  
  1161.     while(1)
  1162.     {
  1163.     switch (State) {
  1164.     case S_Get_DLE :
  1165.         ttime = 300;
  1166.  
  1167.         if (ST_Check_Abort() && !Aborting)
  1168.         {
  1169.             ST_Display_String (STMsg,
  1170.                 "Aborting the upload per your request");
  1171.             Send_Failure ("AAborted by user");
  1172.             return(FALSE);
  1173.         }
  1174.  
  1175.         if (!read_byte()  )
  1176.             State = S_Timed_Out;
  1177.         else
  1178.         {
  1179.             if (ch == dle)
  1180.                 State = S_Get_Num;
  1181.             else if (ch == nak )
  1182.                 State = S_Send_ENQ;
  1183.             else if (ch == etx )
  1184.                 State = S_Send_NAK;
  1185.         }
  1186.         break;
  1187.  
  1188.     case S_Get_Num :
  1189.         if (!read_byte() )
  1190.             State = S_Timed_Out;
  1191.         else if ((ch >= '0') && (ch <= '9'))
  1192.             State = S_Have_ACK;           /* Received ACK */
  1193.         else if (ch == 'B' )
  1194.         {
  1195.             if (!Aborting)
  1196.                 State = S_Get_Packet; /* Try to receive a Packet */
  1197.             else State = S_Skip_Packet;   /* Try to skip a Packet */
  1198.         }
  1199.         else if (ch == nak)
  1200.             State = S_Send_ENQ;
  1201.         else if (ch == ';')
  1202.         {    /* Received a WACK (Wait Acknowledge) */
  1203.             ST_Display_Value (STComRead, R_Com_Data);
  1204.             State = S_Get_DLE;
  1205.         }
  1206.         else State = S_Timed_Out;
  1207.         break;
  1208.  
  1209.     case S_Get_Packet :
  1210.         if (Read_Packet (TRUE, TRUE) )
  1211.         {
  1212.             Packet_Received = TRUE;
  1213.  
  1214.             if (R_buffer [0] == 'F')  /* Check for Failure Packet */
  1215.             {
  1216.                 Send_ACK();
  1217.                 return(FALSE);
  1218.             }
  1219.  
  1220.             State = S_Get_DLE;     /* Stay here to find the ACK */
  1221.         }
  1222.         else State = S_Get_DLE;         /* Receive failed; keep watching for ACK */
  1223.         break;
  1224.  
  1225.     case S_Skip_Packet :    /* Skip an incoming Packet */
  1226.         if (!read_byte())
  1227.             State = S_Timed_Out;
  1228.         else if (ch == etx )
  1229.         {                  /* Get the Checksum or CRC */
  1230.             if (!read_masked_byte())
  1231.                 State = S_Timed_Out;
  1232.             else if (!Use_CRC)
  1233.                 State = S_Get_DLE;
  1234.             else if (!read_masked_byte())
  1235.                 State = S_Timed_Out;
  1236.             else State = S_Get_DLE;
  1237.         }
  1238.         break;
  1239.  
  1240.     case S_Have_ACK :
  1241.         block_num = ch - '0';
  1242.         ST_Display_Value (STComSent, S_Com_Data);
  1243.         ST_Display_Value (STComRead, R_Com_Data);
  1244.  
  1245.         if (SA_Buf [SA_Next_to_ACK].seq == block_num  )
  1246.         {                  /* This is the one we're waiting for */
  1247.             SA_Next_to_ACK = Incr_SA (SA_Next_to_ACK);
  1248.             SA_Waiting = SA_Waiting - 1;
  1249.  
  1250.             if (SA_Error_Count > 0 )     /* Apply heuristic to control */
  1251.             SA_Error_Count--; /* Upload Performance degradation */
  1252.  
  1253.             return(TRUE);
  1254.         }
  1255.         else if ((SA_Buf [Incr_SA (SA_Next_to_ACK)].seq == block_num) &&
  1256.             SA_Waiting == 2)
  1257.         {                 /* Must have missed an ACK */
  1258.             SA_Next_to_ACK = Incr_SA (SA_Next_to_ACK);
  1259.             SA_Next_to_ACK = Incr_SA (SA_Next_to_ACK);
  1260.             SA_Waiting = SA_Waiting - 2;
  1261.  
  1262.             if (SA_Error_Count > 0)
  1263.                 SA_Error_Count--;
  1264.  
  1265.             return(TRUE);
  1266.         }
  1267.         else if (SA_Buf [SA_Next_to_ACK].seq == Incr_Seq (block_num) )
  1268.         {
  1269.             if (Sent_ENQ)
  1270.                 State = S_Send_Data; /* Remote missed first block */
  1271.             else State = S_Get_DLE;       /* Duplicate ACK */
  1272.         }
  1273.         else
  1274.         {
  1275.             if (!Aborting)        /* While aborting, ignore any */
  1276.                 State = S_Timed_Out; /* ACKs that have been sent   */
  1277.             else State = S_Get_DLE;       /* which are not for the failure */
  1278.         }                                   /* Packet. */
  1279.  
  1280.         Sent_ENQ = FALSE;
  1281.         break;
  1282.  
  1283.     case S_Timed_Out :
  1284.         State = S_Send_ENQ;
  1285.         break;
  1286.  
  1287.     case S_Send_NAK :
  1288.         errors++;
  1289.         S_Error_Count++;
  1290.         ST_Display_Value (STErrSent, S_Error_Count);
  1291.  
  1292.         if (errors > max_Errors)
  1293.             return(FALSE);
  1294.  
  1295.         Send_NAK();
  1296.  
  1297.         State = S_Get_DLE;
  1298.         break;
  1299.  
  1300.     case S_Send_ENQ :
  1301.         errors++;
  1302.         S_Error_Count++;
  1303.         ST_Display_Value (STErrSent, S_Error_Count);
  1304.  
  1305.         if ((errors > max_Errors) || (Aborting && (errors > 3)))
  1306.             return(FALSE);
  1307.  
  1308.         ch = ReSync();
  1309.         if (ch == -1)
  1310.             State = S_Get_DLE;
  1311.         else if (ch == 'B')
  1312.         {
  1313.             if( !Aborting )
  1314.                 State = S_Get_Packet;    /* Try to receive a Packet */
  1315.             else
  1316.                 State = S_Skip_Packet;    /* Try to skip a Packet */
  1317.         }
  1318.         else State = S_Have_ACK;
  1319.         Sent_ENQ   = TRUE;
  1320.         break;
  1321.  
  1322.     case S_Send_Data :
  1323.         SA_Error_Count += 3;
  1324.  
  1325.         if (SA_Error_Count >= 12) /* Stop Upload Send Ahead if too many */
  1326.         SA_Max = 1;           /* errors have occured */
  1327.  
  1328.         SA_Index = SA_Next_to_ACK;
  1329.  
  1330.         for (i = 1; i<=SA_Waiting; i++ )
  1331.         {
  1332.             Send_Data (SA_Index);
  1333.             SA_Index = Incr_SA (SA_Index);
  1334.         }
  1335.  
  1336.         State = S_Get_DLE;
  1337.         Sent_ENQ = FALSE;
  1338.         break;
  1339.     }
  1340.     }
  1341. } /* Get_ACK */
  1342.  
  1343. STATIC    int    send_Packet (size)
  1344. int    size;
  1345. {
  1346.     while (SA_Waiting >= SA_Max) /* Allow for possible drop out of Send Ahead */
  1347.     {
  1348.         if (!Get_ACK() )
  1349.             return(FALSE);
  1350.     }
  1351.  
  1352.     seq_num = Incr_Seq (seq_num);
  1353.     SA_Buf [SA_Next_to_Fill].seq = seq_num;
  1354.     SA_Buf [SA_Next_to_Fill].num = size;
  1355.     Send_Data (SA_Next_to_Fill);
  1356.     SA_Next_to_Fill = Incr_SA (SA_Next_to_Fill);
  1357.     SA_Waiting = SA_Waiting + 1;
  1358.     S_Packet_Count++;
  1359.     ST_Display_Value (STComSent, S_Com_Data);
  1360.     ST_Display_Value (STPacSent, S_Packet_Count);
  1361.     return(TRUE);
  1362. }
  1363.  
  1364. /*
  1365.   SA_Flush is called after sending the last Packet to get host's
  1366.   ACKs on outstanding Packets.
  1367. */
  1368.  
  1369. STATIC    int    SA_Flush()
  1370. {
  1371.     while (SA_Waiting > 0)
  1372.     {
  1373.         if (!Get_ACK())
  1374.             return(FALSE);
  1375.     }
  1376.     return( TRUE );
  1377. }
  1378.  
  1379. STATIC    void Send_Failure (Reason)
  1380. char    Reason[];
  1381. {
  1382.     int    i;
  1383.     buf_type    *p;
  1384.  
  1385.     SA_Next_to_ACK = 0;
  1386.     SA_Next_to_Fill = 0;
  1387.     SA_Waiting = 0;
  1388.     Aborting   = TRUE;          /* Inform Get_ACK we're aborting ]*/
  1389.  
  1390.     p = &SA_Buf [0];
  1391.     p->buf [0] = 'F';
  1392.     for (i = 1; i<=strlen(Reason); i++ )
  1393.         p->buf [i] = (Reason [i]);
  1394.  
  1395.     if ( send_Packet (strlen(Reason)) )
  1396.         SA_Flush();   /* Gotta wait for the Initiator to ACK it */
  1397. }
  1398.  
  1399. /* Send_File is called to send a file to the host */
  1400.  
  1401. STATIC    int    Send_File (name)
  1402. char    name[];
  1403. {
  1404.     int    n;
  1405.       FILE    *data_File;
  1406.     buf_type    *p;
  1407.  
  1408.     data_File = fopen (name,"rb");
  1409.  
  1410.     if (data_File == 0 )
  1411.     {
  1412.         ST_Display_String (STMsg, "Cannot find that file");
  1413.         Send_Failure ("MFile not found");
  1414.         return(FALSE);
  1415.     }
  1416.  
  1417.     fseek(data_File,0L,2);        /* seek to end of file */
  1418.     S_Remaining = ftell(data_File);    /* how long is this file ? */
  1419.     fseek(data_File,0L,0);        /* back to the start, ready to go */
  1420.     ST_Display_Value (STUplRem, S_Remaining);
  1421. /* Send_File_Information here ? */
  1422.  
  1423. /*----------------
  1424.     S_Com_Data = 0;
  1425.     R_Com_Data = 0;
  1426.     e_timer = gtime(NULL);
  1427. -------------------*/
  1428.     do
  1429.     {
  1430.         p = &SA_Buf [SA_Next_to_Fill];
  1431.             p->buf [0] = 'N';
  1432.             n = fread (&p->buf[1], 1, Buffer_Size, data_File);
  1433.  
  1434.         if (n > 0)
  1435.         {
  1436.             if (send_Packet (n) == FALSE)
  1437.             {
  1438.                 fclose(data_File);
  1439.                 return(FALSE);
  1440.             }
  1441.  
  1442.             S_File_Data = S_File_Data +  (n);
  1443.             S_File_Size = S_File_Size +  (n);
  1444.             S_Remaining = S_Remaining -  (n);
  1445.             ST_Display_Value (STUplSize, S_File_Size);
  1446.             ST_Display_Value (STDataSent, S_File_Data);
  1447.             ST_Display_Value (STUplRem, S_Remaining);
  1448.             Time_Estimate = gtime(NULL) - e_timer;
  1449.             ST_Display_Value (STElapsed, Time_Estimate);
  1450.  
  1451.             if (Time_Estimate != 0)
  1452.             {
  1453.                 Com_Rate = S_Com_Data / Time_Estimate;
  1454.                 Data_Rate = S_File_Data / Time_Estimate;
  1455.                 ST_Display_Value (STComRate, Com_Rate);
  1456.                 ST_Display_Value (STDataRate, Data_Rate);
  1457.  
  1458.                 if (Data_Rate != 0)
  1459.                 {
  1460.                     Time_Estimate = S_Remaining / Data_Rate;
  1461.                     ST_Display_Value (STRemTime, Time_Estimate);
  1462.                 }
  1463.             }
  1464.         }
  1465.     } while(n > 0);
  1466.  
  1467.     if (ferror(data_File) != 0)
  1468.     {
  1469.         Send_Failure ("EFile read failure");
  1470.         ST_Display_String (STMsg, "Read failure...aborting");
  1471.         fclose(data_File);
  1472.         return(FALSE);
  1473.     }
  1474.  
  1475. /* Inform host that the file was sent */
  1476.  
  1477.     p = &SA_Buf [SA_Next_to_Fill];
  1478.     p->buf [0] = 'T';
  1479.     p->buf [1] = 'C';
  1480.  
  1481.     if (send_Packet (2) == FALSE)
  1482.     {
  1483.         fclose (data_File);
  1484.         return(FALSE);
  1485.     }
  1486.     else
  1487.     {
  1488.         fclose (data_File);
  1489.         if (!SA_Flush())
  1490.             return(FALSE);
  1491.         return(TRUE);
  1492.     }
  1493.  
  1494. } /* Send_File */
  1495.  
  1496. /*
  1497.     Do_Transport_Parameters is called when a Packet type of + is received.
  1498.     It sends a Packet of Our local B Plus parameters and sets the Our_xx
  1499.     parameters to the minimum of the Initiator's and Our own parameters.
  1500. */
  1501.  
  1502. STATIC    void Do_Transport_Parameters()
  1503. {
  1504.     int    Quote_Set_Present;
  1505.     int    i;
  1506.     buf_type    *p;
  1507.  
  1508.     if (BP_Special_Quoting)
  1509.     {
  1510.         for( i=0; i<8; i++ )
  1511.             Our_QS[i] = BP_Special_Quote_Set[i];
  1512.     }
  1513.     else
  1514.     {
  1515.         for( i=0; i<8; i++ )
  1516.             Our_QS[i] = DQ_Minimal[i];
  1517.     }
  1518.  
  1519.     for (i = R_Size + 1; i<=512; i++ ) R_buffer [i] = 0;
  1520.  
  1521.     His_WS = R_buffer [1];     /* Pick out Initiator's parameters */
  1522.     His_WR = R_buffer [2];
  1523.     His_BS = R_buffer [3];
  1524.     His_CM = R_buffer [4];
  1525.  
  1526.     His_QS [0] = R_buffer [7];
  1527.     His_QS [1] = R_buffer [8];
  1528.     His_QS [2] = R_buffer [9];
  1529.     His_QS [3] = R_buffer [10];
  1530.     His_QS [4] = R_buffer [11];
  1531.     His_QS [5] = R_buffer [12];
  1532.     His_QS [6] = R_buffer [13];
  1533.     His_QS [7] = R_buffer [14];
  1534.  
  1535.     His_DR = R_buffer [15];
  1536.     His_UR = R_buffer [16];
  1537.     His_FI = R_buffer [17];
  1538.  
  1539.     if (R_Size >= 14)
  1540.         Quote_Set_Present = TRUE;
  1541.     else Quote_Set_Present = FALSE;
  1542.  
  1543.     p = &SA_Buf [SA_Next_to_Fill];
  1544.     p->buf [0] = '+';  /* Prepare to return Our own parameters */
  1545.     p->buf [1] = Def_WS;
  1546.     p->buf [2] = Def_WR;
  1547.     p->buf [3] = Def_BS;
  1548.     p->buf [4] = Def_CM;
  1549.     p->buf [5] = Def_DQ;
  1550.     p->buf [6] = 0;          /* No transport layer here */
  1551.  
  1552.     for (i = 0; i<=7; i++ )
  1553.         p->buf [i + 7] = Our_QS [i];
  1554.  
  1555.     if (BP_Auto_Resume)      /* Set Download Resume according to */
  1556.         Def_DR = 2;       /* user's preference */
  1557.     else Def_DR = 1;
  1558.  
  1559.     p->buf [15] = Def_DR;
  1560.     p->buf [16] = Def_UR;
  1561.     p->buf [17] = Def_FI;
  1562.  
  1563.     Update_Quote_Table (DQ_Full);   /* Send the + Packet w/ full quoting */
  1564.  
  1565.     if (!send_Packet (17) )
  1566.         return;
  1567.  
  1568.     if (SA_Flush())                 /* Wait for host's ACK on Our Packet */
  1569.     {
  1570.         if (His_WS < Def_WR)      /* Take minimal subset of Transport Params. */
  1571.             Our_WR = His_WS;   /* If he can send ahead, we can receive it. */
  1572.         else Our_WR = Def_WR;
  1573.  
  1574.         if (His_WR < Def_WS)      /* If he can receive send ahead, we can send it. */
  1575.             Our_WS = His_WR;
  1576.         else Our_WS = Def_WS;
  1577.  
  1578.  
  1579.         if( His_BS < Def_BS)
  1580.             Our_BS = His_BS;
  1581.         else Our_BS = Def_BS;
  1582.  
  1583.         if (His_CM < Def_CM)
  1584.             Our_CM = His_CM;
  1585.         else Our_CM = Def_CM;
  1586.  
  1587.         if (His_DR < Def_DR)
  1588.             Our_DR = His_DR;
  1589.         else Our_DR = Def_DR;
  1590.  
  1591.         if (His_UR < Def_UR)
  1592.             Our_UR = His_UR;
  1593.         else Our_UR = Def_UR;
  1594.  
  1595.         if (His_FI < Def_FI)
  1596.             Our_FI = His_FI;
  1597.         else Our_FI = Def_FI;
  1598.  
  1599.         if (Our_BS == 0)
  1600.             Our_BS = 4;    /* Default */
  1601.  
  1602.         Buffer_Size = Our_BS * 128;
  1603.  
  1604.         B_Plus = TRUE;
  1605.  
  1606.         if (Our_CM == 1)
  1607.             Use_CRC = TRUE;
  1608.  
  1609.         if (Our_WS != 0)
  1610.             SA_Max = Max_SA;
  1611.     }
  1612.  
  1613.     Clear_Quote_Table();            /* Restore Our Quoting Set */
  1614.     Update_Quote_Table (Our_QS);
  1615.  
  1616.     if (Quote_Set_Present)     /* Insert Initiator's Quote Set */
  1617.         Update_Quote_Table (His_QS);
  1618. }
  1619.  
  1620. /* Check_Keep is called from Receive_File when a fatal error */
  1621. /* occurs.  It asks the user if the file should be retained */
  1622.  
  1623. STATIC    void Check_Keep (data_File, Name)
  1624. FILE    *data_File;
  1625. char    Name[];
  1626. {
  1627.     char    yn;
  1628.     char    str[80];
  1629.  
  1630.     fclose (data_File);
  1631.  
  1632.     if ((!BP_Auto_Resume) || (!B_Plus) || (Our_DR == 0))
  1633.     {
  1634.         strcpy( str, "Do you wish to retain the partial " );
  1635.         strcat( str, Name );
  1636.         strcat( str, "?" );
  1637.         ST_Yes_or_No( str, &yn );
  1638.     }
  1639.     else
  1640.         yn = 'Y';
  1641.  
  1642.     if (yn == 'N')
  1643.     {
  1644.         unlink ( Name );
  1645.         ST_Display_String (STMsg, "File erased.");
  1646.     }
  1647.     else
  1648.     {
  1649. /* implementation dependent option: Hide the file from casual view */
  1650.         ST_Display_String (STMsg, "File retained.");
  1651.     }
  1652. }
  1653.  
  1654. /* Process_File_Information is called from Receive_File when a TI Packet */
  1655. /* is received.  It extracts the desired information from the Packet.    */
  1656.  
  1657. STATIC    char    Val_Str[50];
  1658. STATIC    int    e_i=0, e_j=0, e_n=0;
  1659.  
  1660. STATIC void Extract_String()   /* Extract next string of characters */
  1661. {
  1662.     int    Digit_Seen;
  1663.  
  1664.     Digit_Seen = FALSE;
  1665.     e_j = 0;
  1666.     while (e_i <= e_n)
  1667.     {
  1668.         if ((R_buffer [e_i] >= '0') && (R_buffer [e_i] <= '9') )
  1669.         {
  1670.             Digit_Seen = TRUE;
  1671.             e_j++;
  1672.             Val_Str [e_j] = R_buffer [e_i];
  1673.         }
  1674.         else if (Digit_Seen)
  1675.         {
  1676.             Val_Str [0] = e_j;
  1677.             return;
  1678.         }
  1679.  
  1680.         e_i++;
  1681.     }
  1682. }
  1683.  
  1684. STATIC    void Process_File_Information()
  1685. {
  1686.     int    i;
  1687.  
  1688.     e_n = R_Size - 1;
  1689.     e_i = 4;       /* Skip data type and compression flag */
  1690.     Extract_String();
  1691. /*    Val (Val_Str, R_Remaining, e_j); */
  1692.     R_Remaining = 0;
  1693.     for( i=1; i<=e_j; i++ )
  1694.         R_Remaining = (R_Remaining * 10) + (Val_Str[i] - '0');
  1695.     R_Remaining = R_Remaining - R_File_Size;  /* Adjust for Dow Resume */
  1696.     ST_Display_Value (STDowRem, R_Remaining);
  1697.  
  1698.   /* Ignore rest of parameters for now */
  1699.  
  1700.     S_Packet_Count = 0;
  1701.     R_Packet_Count = 0;
  1702. }
  1703.  
  1704. /* Receive_File is called to receive a file from the host */
  1705.  
  1706. STATIC    int    Receive_File (Name)
  1707. char    Name[];
  1708. {
  1709.     FILE    *Data_File;
  1710.     int    status;
  1711.     long    File_Length;      /* For download resumption */
  1712.     lstr    Work_String;
  1713.     int    Packet_Len;
  1714.     int    i, n;
  1715.     char    yn;
  1716.     char    Dow_Type;
  1717.     buf_type    *p;
  1718.  
  1719.     Dow_Type = 'D';         /* Assume normal downloading */
  1720.  
  1721.     Data_File = fopen( Name, "rwb" );    /* open for r/w first */
  1722.  
  1723.     if (Data_File != NULL)    /* this file already exists */
  1724.     {                   /* See if we can try automatic resume */
  1725.         if ((Our_DR > 1) && BP_Auto_Resume)
  1726.             Dow_Type = 'R';  /* Remote supports `Tf', let's try */
  1727.         else if ((Our_DR > 0))
  1728.         {
  1729.             ST_Display_String (STMsg, "File already exists.");
  1730.             ST_Yes_or_No ("Do you wish to resume downloading? ", &yn);
  1731.  
  1732.             if (yn == 'Y')
  1733.                 Dow_Type = 'R';
  1734.             else
  1735.                 ST_Display_String (STMsg, "File being overwritten.");
  1736.         }
  1737.     }
  1738.  
  1739.     switch( Dow_Type ) {
  1740.     case 'D':
  1741.         if( Data_File )
  1742.             fclose( Data_File );    /* close the read/write file */
  1743.         Data_File = fopen( Name, "wb" );    /* open for write */
  1744.         if (Data_File == NULL)
  1745.         {
  1746.             Send_Failure ("CCannot create file");
  1747.             return(FALSE);
  1748.         }
  1749.         Send_ACK();
  1750.         break;
  1751.  
  1752.     case 'R' :
  1753.                      /* Resume download */
  1754.         /* file is open and at start */
  1755.         ST_Display_String (STMsg, "Calculating CRC");
  1756.  
  1757.         p = &SA_Buf [SA_Next_to_Fill];
  1758.         if (Dow_Type == 'R')
  1759.         {
  1760.             checksum = Init_CRC (0xffff);
  1761.             do {
  1762.                 n = fread (&p->buf [0], 1, Buffer_Size,
  1763.                     Data_File);
  1764.                 for (i = 0; i<n; i++ )
  1765.                     checksum =
  1766.                         Upd_CRC((unsigned int)p->buf [i]);
  1767.                     } while( n > 0 );
  1768.         }
  1769.         else
  1770.             checksum = 0;
  1771.  
  1772.         p->buf [0] = 'T';
  1773.         p->buf [1] = 'r';
  1774.  
  1775.         Packet_Len = 2;
  1776.         File_Length = ftell(Data_File);
  1777.  
  1778.         ltoa (File_Length, Work_String);
  1779.         strcat( Work_String, " " );
  1780.  
  1781.         for (i = 0; i<strlen(Work_String); i++ )
  1782.         {
  1783.             p->buf [Packet_Len] = Work_String [i];
  1784.             Packet_Len++;
  1785.         }
  1786.  
  1787.         ltoa ((long)checksum, Work_String);
  1788.         strcat( Work_String, " " );
  1789.  
  1790.         for (i = 0; i<strlen(Work_String); i++ )
  1791.         {
  1792.             p->buf [Packet_Len] = Work_String [i];
  1793.             Packet_Len++;
  1794.         }
  1795.  
  1796.         if (!send_Packet (Packet_Len - 1)) /* Send_Data sends 0..Size */
  1797.         {
  1798.             fclose (Data_File);
  1799.             return(FALSE);
  1800.         }
  1801.  
  1802.         if (!SA_Flush())
  1803.         {
  1804.             fclose (Data_File);
  1805.             return(FALSE);
  1806.         }
  1807.  
  1808.         R_File_Size = File_Length;
  1809.         ST_Display_Value (STDowSize, R_File_Size);
  1810.         ST_Display_String (STMsg, "Host calculating CRC...");
  1811.         Resume_Flag = TRUE;
  1812.         break;
  1813.     }
  1814.  
  1815.  
  1816. /*
  1817.   Process each incoming Packet until 'TC' Packet received or failure
  1818. */
  1819.  
  1820.     R_Packet_Count = 0;
  1821.     S_Packet_Count = 0;
  1822.  
  1823.     if( BP_Use_File_Size )
  1824.         R_Remaining = BP_File_Size;
  1825.     else
  1826.         R_Remaining = 0;
  1827.   while(TRUE)
  1828.     {
  1829.       if (Read_Packet (FALSE, FALSE))
  1830.           {
  1831.             switch (R_buffer[0]) {
  1832.               case 'N' :
  1833.         if( Resume_Flag )
  1834.         {
  1835.             ST_Display_String( STMsg, "Resuming Download" );
  1836.             Resume_Flag = FALSE;
  1837.         }
  1838.  
  1839.         status = fwrite( &R_buffer[1], 1, R_Size - 1, Data_File );
  1840.  
  1841.                   if ((status != (R_Size - 1)))
  1842.                     {
  1843.                       ST_Display_String (STMsg, "Write failure...aborting");
  1844.                       Send_Failure ("EWrite failure");
  1845.                       Check_Keep (Data_File, Name);
  1846.                       return(FALSE);
  1847.                     }
  1848.                   R_File_Data = R_File_Data + (R_Size - 1);
  1849.           ST_Display_Value (STDataRead, R_File_Data);
  1850.                   R_File_Size = R_File_Size +  (status);
  1851.                   ST_Display_Value (STDowSize, R_File_Size);
  1852.  
  1853.                   Time_Estimate = gtime(NULL) - e_timer;
  1854.                   ST_Display_Value (STElapsed, Time_Estimate);
  1855.  
  1856.                   if (Time_Estimate != 0)
  1857.                     {
  1858.                       Com_Rate = R_Com_Data / Time_Estimate;
  1859.                       Data_Rate = R_File_Data / Time_Estimate;
  1860.                       ST_Display_Value (STComRate, Com_Rate);
  1861.                       ST_Display_Value (STDataRate, Data_Rate);
  1862.                     }
  1863.                   else Data_Rate = 0;
  1864.  
  1865.                   if (R_Remaining != 0)
  1866.                              /* Decrement remaining byte count */
  1867.                     {
  1868.                       R_Remaining = R_Remaining - (R_Size - 1);
  1869.                       ST_Display_Value (STDowRem, R_Remaining);
  1870.  
  1871.  
  1872.                       if (Data_Rate != 0)
  1873.                         {
  1874.                           Time_Estimate = R_Remaining / Data_Rate;
  1875.                           ST_Display_Value (STRemTime, Time_Estimate);
  1876.                         }
  1877.                     }
  1878.  
  1879.  
  1880.                   Send_ACK();
  1881.                 break;
  1882.  
  1883.               case 'T' :
  1884.                   if (R_buffer[1] == 'C')
  1885.                     {
  1886.                       ST_Display_String (STMsg, "*** Transfer Complete ***");
  1887.                       status = fclose (Data_File);
  1888.  
  1889.                       if (status == EOF)
  1890.                         {
  1891.                           ST_Display_String (STMsg, "Failure during close...aborting");
  1892.                           Send_Failure ("EError during close");
  1893.                           Check_Keep (Data_File, Name);
  1894.                           return(FALSE);
  1895.                         }
  1896.  
  1897.                       Send_ACK();
  1898.                       return(TRUE);
  1899.                     }
  1900.                 else if (R_buffer [1] == 'I')
  1901.                   {
  1902.                     Send_ACK();
  1903.                     Process_File_Information();
  1904.                   }
  1905.                 else if ((R_buffer [1] == 'f') && BP_Auto_Resume)
  1906.                               /* `Tf' Packet implies host failed the */
  1907.                   {          /* CRC check on a DOW resume */
  1908.             fclose (Data_File);       /* So...replace the file */
  1909.             Data_File = fopen(Name, "wb");
  1910.             if (Data_File == NULL)
  1911.             {
  1912.                 Send_Failure ("CCannot create file");
  1913.  
  1914.                 ST_Display_String (STMsg,
  1915.                     "CRC check failed; cannot create file");
  1916.                 return(FALSE);
  1917.             }
  1918.  
  1919.                     if (Our_FI != 0 || BP_Use_File_Size)
  1920.                       R_Remaining = R_Remaining + R_File_Size;
  1921.  
  1922.                     R_File_Size = 0;
  1923.                     ST_Display_String (STMsg, "CRC check failed; overwriting file");
  1924.             Resume_Flag = FALSE;
  1925.             e_timer = gtime(NULL);
  1926.             S_Com_Data = 0;
  1927.             R_Com_Data = 0;
  1928.                     Send_ACK();
  1929.                   }
  1930.                 else
  1931.                   {
  1932.                     ST_Display_String (STMsg, "Invalid termination Packet...aborting");
  1933.                     Send_Failure ("NInvalid T Packet");
  1934.                     Check_Keep (Data_File, Name);
  1935.                     return(FALSE);
  1936.                   }
  1937.               break;
  1938.  
  1939.               case 'F' :
  1940.                   Send_ACK();
  1941.                   ST_Display_String (STMsg, "Failure Packet received...aborting");
  1942.                   Check_Keep (Data_File, Name);
  1943.                   return(FALSE);
  1944.  
  1945.             }
  1946.  
  1947.           }
  1948.         else
  1949.           {
  1950.             if (!Aborting)
  1951.               ST_Display_String (STMsg, "Download failure");
  1952.             Check_Keep (Data_File, Name);
  1953.             return(FALSE);
  1954.           }
  1955.     }
  1956.  
  1957. } /* Receive_File */
  1958.  
  1959. /* =================================================================== */
  1960.  
  1961. void BP_DLE_Seen()
  1962. {   /* DLE_Seen */
  1963.  
  1964.     int    i;
  1965.  
  1966.   /*
  1967.     Begin by getting the next character.  If it is <B> then enter the
  1968.     B_Protocol state.  Otherwise simply return.
  1969.   */
  1970.  
  1971.   Port_Update_Rate = 30;
  1972.  
  1973.     ST_Initialize();
  1974.  
  1975.   if (!read_byte())
  1976.     return;
  1977.  
  1978.  
  1979.   if (ch != 'B')
  1980.     return;
  1981.  
  1982.   SA_Next_to_ACK  = 0;    /* Initialize Send-ahead variables */
  1983.   SA_Next_to_Fill = 0;
  1984.   SA_Waiting      = 0;
  1985.   Aborting        = FALSE;
  1986.   Packet_Received = FALSE;
  1987.  
  1988.   /* Establish Data Block Size as a function of the Baud */
  1989.   /* The intent is to keep the per-Packet time to 4-5 seconds */
  1990.  
  1991.   PortBps = bps;       /* Apend FMR version */
  1992.  
  1993.   switch (PortBps) {
  1994.     case bps300:
  1995.         Def_BS = 1;
  1996.         Port_Update_Rate = 30;
  1997.     break;
  1998.     case bps600:
  1999.     case bps1200:
  2000.         Def_BS = 4;
  2001.         Port_Update_Rate = 120;
  2002.     break;
  2003.     case bps2400:
  2004.     case bps4800:
  2005.     case bps9600:
  2006.         Def_BS = 8;
  2007.         Port_Update_Rate = 240;
  2008.     break;
  2009.     }
  2010.  
  2011.   /*  <DLE><B> received; begin B Protocol */
  2012.  
  2013.   xoff_flag   = TRUE;
  2014.  
  2015.   R_Counter   = 0;
  2016.   S_Counter   = 0;
  2017.   R_File_Data = 0;
  2018.   S_File_Data = 0;
  2019.   R_Com_Data  = 0;
  2020.   S_Com_Data  =  (0);
  2021.   S_Packet_Count =  (0);
  2022.   R_Packet_Count =  (0);
  2023.   S_File_Size =  (0);
  2024.   R_File_Size =  (0);
  2025.   S_Error_Count =  (0);
  2026.   R_Error_Count =  (0);
  2027.     Resume_Flag = FALSE;
  2028.  
  2029.   if (Read_Packet (TRUE, FALSE))
  2030.       {
  2031.         /* Dispatch on the type of Packet just received */
  2032.  
  2033.         switch (R_buffer[0]) {
  2034.           case 'T':                      /* File Transfer Application */
  2035. /*                 ST_Initialize();*/
  2036.         ST_Display_Value (STComRead, R_Com_Data);
  2037.         S_Com_Data = 0;
  2038.         R_Com_Data = 0;
  2039.         e_timer = gtime(NULL);
  2040.  
  2041.         switch (R_buffer[1]) {
  2042.                    case 'D' :
  2043.             ST_Display_String (STUpDow, "Downloading ");
  2044.             break;
  2045.                    case 'U' :
  2046.             ST_Display_String (STUpDow, "Uploading ");
  2047.             break;
  2048.                    default:
  2049.                        ST_Display_String (STMsg, "Unimplemented Transfer Function");
  2050.                        Send_Failure ("NUnimplemented Transfer function");
  2051.                        ST_Terminate();
  2052.                        return;
  2053.                  }
  2054.  
  2055.                  switch (R_buffer[2]) {
  2056.                    case 'A':
  2057.             ST_Display_String (STType, "ASCII");
  2058.             break;
  2059.                    case 'B':
  2060.             ST_Display_String (STType, "Binary");
  2061.             break;
  2062.                    default:
  2063.                        ST_Display_String (STMsg, "Unimplemented File Type");
  2064.                        Send_Failure ("NUnimplemented file type");
  2065.                        ST_Terminate();
  2066.                        return;
  2067.                  }
  2068.  
  2069.                  i = 2;
  2070.          filename[0] = '\0';
  2071.  
  2072.                  while ( R_buffer[i] != 0 ) {
  2073.             if ( i >= (R_Size - 1)) {
  2074.             filename[i - 2] = '\0';
  2075.             break;
  2076.             }
  2077.             i++;
  2078.             filename[i-3] = R_buffer[i];
  2079.                  }
  2080.  
  2081.          ST_Display_String (STFile, filename);
  2082.                  S_Packet_Count =  (0);
  2083.                  R_Packet_Count =  (0);
  2084.  
  2085.                  if (R_buffer[1] == 'U')
  2086.                    Send_File (filename);
  2087.                  else
  2088.                    Receive_File (filename);
  2089.  
  2090.                  ST_Terminate();
  2091.                break;
  2092.  
  2093.           case '+':          /* Received Transport Parameters Packet */
  2094.               Do_Transport_Parameters();
  2095.         break;
  2096.  
  2097.           default:
  2098.                    /* Unknown Packet; tell the host we don't know */
  2099.               Send_Failure ("NUnknown Packet Type");
  2100.         break;
  2101.  
  2102.         }  /* of case */
  2103.  
  2104.       }    /* of if Read_Packet then*/
  2105. } /* DLE_Seen */
  2106.